package org.lc.service.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import jakarta.annotation.Resource;
import org.lc.platform.base.domain.JwtUser;
import org.lc.platform.base.util.SmEncryptUtil;
import org.lc.platform.mybatis.crud.service.impl.CrudBaseServiceImpl;
import org.lc.platform.mybatis.manager.query.QueryBuilder;
import org.lc.service.system.config.InitSystemDataConfig;
import org.lc.service.system.dto.SysUserDto;
import org.lc.service.system.entity.*;
import org.lc.service.system.mapper.SysUserMapper;
import org.lc.service.system.service.SysUserService;
import org.lc.service.system.vo.SysUserVo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service
public class SysUserServiceImpl extends CrudBaseServiceImpl<SysUserDto, SysUserVo, SysUserMapper, SysUser> implements SysUserService {

    @Value("${properties.common.init-system.default-account:''}")
    private String defaultAccount;

    @Override
    public QueryBuilder<SysUser> getQueryBuilder(SysUserDto query, QueryBuilder<SysUser> queryBuilder) {
        queryBuilder.like(StrUtil.isNotEmpty(query.getName()), "name", query.getName());
        queryBuilder.relation(SysRole.class).relation(SysDepartment.class);
        if (query.getDepartmentId() != null) {
            var userIds = Db.list(Db.lambdaQuery(SysDepartmentUser.class).eq(SysDepartmentUser::getSysDepartmentId, query.getDepartmentId()).getWrapper());
            if (userIds != null) {
                var ids = userIds.stream().map(SysDepartmentUser::getSysUserId).toList();
                if (ids.isEmpty()) {
                    queryBuilder.isNull("id");
                } else {
                    queryBuilder.in("id", ids);
                }
            }
        }
        if (!defaultAccount.isEmpty()) {
            queryBuilder.ne("account", defaultAccount);
        }
        return queryBuilder;
    }

    @Override
    public SysUserVo Convertor(SysUser data) {
        return BeanUtil.copyProperties(data, SysUserVo.class);
    }

    @Override
    @Transactional
    public Boolean createBaseOne(SysUser body) {
        String account = body.getAccount();
        if (StrUtil.isNotEmpty(account)) {
            String passWord = SmEncryptUtil.passWordEncrypt(account + "A!");
            body.setPassword(passWord);
        }
        super.createBaseOne(body);
        saveRoles(body.getId(), body.getRoles());
        saveDepartment(body.getId(), body.getDepartment());
        return true;
    }

    @Override
    @Transactional
    public Boolean updateBaseOne(String id, SysUser data) {
        saveRoles(id, data.getRoles());
        saveDepartment(id, data.getDepartment());
        return super.updateBaseOne(id, data);
    }

    private void saveRoles(String userId, List<SysRole> roleIds) {
        var warp = Db.lambdaQuery(SysRoleUser.class).getWrapper();
        warp.eq(userId != null, SysRoleUser::getSysUserId, userId);
        if (Db.count(warp) > 0) {
            Db.remove(warp);
        }
        if (roleIds != null) {
            List<SysRoleUser> data = roleIds.stream().map(r -> new SysRoleUser(r.getId(), userId)).toList();
            Db.saveBatch(data);
        }
    }

    private void saveDepartment(String userId, List<SysDepartment> departmentIds) {
        var warp = Db.lambdaQuery(SysDepartmentUser.class).getWrapper();
        warp.eq(userId != null, SysDepartmentUser::getSysUserId, userId);
        if (Db.count(warp) > 0) {
            Db.remove(warp);
        }
        if (departmentIds != null) {
            List<SysDepartmentUser> data = departmentIds.stream().map(r -> new SysDepartmentUser(userId, r.getId())).toList();
            Db.saveBatch(data);
        }
    }

    @Override
    public List<SysRoleAclApi> getSysRoleAclApi(String userId) {
        if (StrUtil.isNotEmpty(userId)) {
            List<SysRoleAclApi> role = this.baseMapper.findRoleByUserId(userId);
            List<SysRoleAclApi> department = this.baseMapper.findDepartmentRoleByUserId(userId);
            if (role != null) {
                if (department != null) {
                    role.addAll(department);
                }
                return role;
            }
        }
        return List.of();
    }

    /**
     * 通过账号查询用户
     *
     * @param userAccount 用户账号
     */
    @Override
    public JwtUser queryUserByAccount(String userAccount) {
        LambdaQueryWrapper<SysUser> ew = new LambdaQueryWrapper<>();
        ew.and(e -> e.eq(SysUser::getAccount, userAccount).or().eq(SysUser::getPhone,
                userAccount));

        var sysUser = this.getOne(ew);
        var user = new JwtUser();
        if (ObjUtil.isNull(sysUser)) {
            return null;
        }
        user.setPassword(sysUser.getPassword());
        user.setForbidden(sysUser.getForbidden());
        user.setUsername(sysUser.getAccount());
        user.setNickName(sysUser.getName());
        user.setUserId(sysUser.getId());
        user.setStatus(sysUser.getStatus());
        List<SysRoleAclApi> raa = getSysRoleAclApi(sysUser.getId());
        raa.forEach(r -> {
            if (ObjUtil.isNotNull(r)) {
                user.addRole(r.getCode());
                user.addAcl(r.getAcl());
                user.addApi(r.getApi());
            }
        });
        return user;
    }
}